home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Samples / SampleCode / Unsupported Libraries / CustomAttribute_Lib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-14  |  32.8 KB  |  1,580 lines  |  [TEXT/MPS ]

  1. /*
  2.  * CustomIO_Lib.c
  3.  *
  4.  *    Demo/Template for writing custom IO functions
  5.  *    
  6.  *    Custom Attribute example
  7.  */
  8.  
  9. #if !defined(QD3D_OBSOLETE)
  10. #define QD3D_OBSOLETE    1
  11. #endif
  12.  
  13. #include <QD3D.h>
  14. #include <QD3DSet.h>
  15.  
  16. #include <QD3DIO.h>
  17. #include <QD3DString.h>
  18. #include <QD3DGeometry.h>
  19. #include <QD3DGroup.h>
  20.  
  21. #include <stdlib.h>
  22.  
  23.     /* Put QD3D_OBSOLETE in header to make old picking code work */
  24. #include "CustomAttribute_Lib.h"
  25.  
  26. /*
  27.  *    This file contains the implementation for the following custom attributes
  28.  *    
  29.  *    name - contains a string object, can be attached to any object below shape
  30.  *    scle - scale, determines the relative scale of an object/group with 1 meter
  31.  *    upvt - up vector, determines the vertical orientation of an object/group
  32.  *    fwvt - forward vector, determines the front orientation of an object/group
  33.  *    url     - allows you to attach an URL to an object/group
  34.  */
  35.  
  36. /*
  37.  * Globals
  38.  */
  39. static TQ3ObjectClass    gNameAttributeClass = NULL,
  40.                         gScaleAttributeClass = NULL,
  41.                         gUpVectorAttributeClass = NULL,
  42.                         gForwardVectorAttributeClass = NULL,
  43.                         gW3AnchorClass = NULL,
  44.                         gW3InlineClass = NULL,
  45.                         gWWWAnchorClass = NULL;
  46.  
  47.  
  48. /*
  49.  *    These are the registration calls for the individual attributes
  50.  */
  51. TQ3Status NameAttribute_Register( void);
  52.  
  53. TQ3Status NameAttribute_Unregister( void);
  54.  
  55. TQ3Status ScaleAttribute_Register( void);
  56.     
  57. TQ3Status ScaleAttribute_Unregister( void);
  58.  
  59. TQ3Status UpVectorAttribute_Register( void);
  60.  
  61. TQ3Status UpVectorAttribute_Unregister( void);
  62.  
  63. TQ3Status ForwardDirectionAttribute_Register( void);
  64.  
  65. TQ3Status ForwardDirectionAttribute_Unregister( void);
  66.  
  67. TQ3Status W3Anchor_Register( void);
  68.  
  69. TQ3Status W3Anchor_UnRegister( void);
  70.  
  71. TQ3Status W3Anchor_Unregister( void);
  72.  
  73. TQ3Status W3Inline_Register( void);
  74.  
  75. TQ3Status W3Inline_Unregister( void);
  76.  
  77. TQ3Status WWWAnchor_Register( void );
  78.  
  79. TQ3Status WWWAnchor_Unregister( void);
  80.  
  81. /**********************************************************************************************
  82.  *
  83.  *                        PUBLIC ROUTINES FOR REGISTRATION AND UNREGISTRATION
  84.  *
  85.  **********************************************************************************************/
  86.  
  87. void RegisterAllCustomAttributes(void)
  88. {
  89.     NameAttribute_Register();
  90.  
  91.     ScaleAttribute_Register();
  92.     
  93.     UpVectorAttribute_Register();
  94.  
  95.     ForwardDirectionAttribute_Register();
  96.  
  97.     W3Anchor_Register();
  98.  
  99.     W3Inline_Register();
  100.  
  101.     WWWAnchor_Register();
  102. }
  103.  
  104.  
  105. void UnregisterAllCustomAttributes(void)
  106. {
  107.     NameAttribute_Unregister();
  108.  
  109.     ScaleAttribute_Unregister();
  110.     
  111.     UpVectorAttribute_Unregister();
  112.  
  113.     ForwardDirectionAttribute_Unregister();
  114.  
  115.     W3Anchor_Unregister();
  116.  
  117.     W3Inline_Unregister();
  118.  
  119.     WWWAnchor_Unregister();
  120. }
  121.  
  122. /**********************************************************************************************
  123.  *
  124.  *                                        NAME custom attribute
  125.  *
  126.  **********************************************************************************************/
  127.  
  128.  
  129. /*
  130.  * Utility function to add a name on an shape object, geometry object, or attribute set
  131.  */
  132.  
  133. TQ3Status    SetName(TQ3Object object, char    *name)
  134. {
  135.     TQ3StringObject    string = NULL;
  136.     TQ3AttributeSet    set = NULL;
  137.     TQ3Status        status = kQ3Success;
  138.     
  139.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  140.         
  141.         string = Q3CString_New(name);
  142.         
  143.         if( string == NULL) {
  144.             status = kQ3Failure;
  145.             goto cleanExit;
  146.         }
  147.             
  148.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  149.             
  150.             Q3Geometry_GetAttributeSet(object, &set);
  151.             
  152.             if( set == NULL ) {
  153.                 set = Q3AttributeSet_New();
  154.                 if( set == NULL ) {
  155.                     status = kQ3Failure;
  156.                     goto cleanExit;
  157.                 }
  158.                 Q3Geometry_SetAttributeSet(object, set);
  159.             }
  160.         } else {
  161.             Q3Shape_GetSet(object, &set);
  162.             
  163.             if( set == NULL ) {
  164.                 set = Q3Set_New();
  165.                 if( set == NULL ) {
  166.                     status = kQ3Failure;
  167.                     goto cleanExit;
  168.                 }
  169.                 Q3Shape_SetSet(object, set);
  170.             }
  171.         }
  172.             
  173.         if( Q3Set_Add(set, kElementTypeName, &string) == kQ3Failure ) {
  174.             status = kQ3Failure;
  175.             goto cleanExit;
  176.         }
  177.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  178.         string = Q3CString_New(name);
  179.         
  180.         if( string == NULL) {
  181.             status = kQ3Failure;
  182.             goto cleanExit;
  183.         }
  184.         
  185.         if( Q3AttributeSet_Add(object, kElementTypeName, &string) == kQ3Failure ) {
  186.             status = kQ3Failure;
  187.             goto cleanExit;
  188.         }
  189.     } else 
  190.         status = kQ3Failure;
  191.         
  192. cleanExit:
  193.     if( string )
  194.         Q3Object_Dispose(string);
  195.     if( set )
  196.         Q3Object_Dispose(set);
  197.     return status;
  198. }
  199.  
  200. /*
  201.  * Static Functions
  202.  */
  203.  
  204. static TQ3Status NameAttribute_Traverse(
  205.     TQ3Object                unused,
  206.     TQ3StringObject            *stringObject,
  207.     TQ3ViewObject            view)
  208. {
  209.     (void) unused;
  210.     
  211.     if (stringObject == NULL || *stringObject == NULL)
  212.         return kQ3Success;
  213.  
  214.     Q3View_SubmitWriteData(view,0,0,0);
  215.  
  216.     if (Q3Object_Submit( *stringObject, view) == kQ3Failure)
  217.         return kQ3Failure;
  218.  
  219.     return kQ3Success;
  220. }
  221.  
  222. static TQ3Status NameAttribute_ReadData(
  223.     TQ3SetObject            attributeSet,
  224.     TQ3FileObject            file)
  225. {
  226.     TQ3StringObject        stringObject;
  227.     TQ3Status            status;
  228.     
  229.     stringObject = Q3File_ReadObject(file);
  230.         
  231.     status = Q3Set_Add(attributeSet, kElementTypeName, &stringObject);
  232.     
  233.     Q3Object_Dispose(stringObject);
  234.  
  235.     /*
  236.         Note that the string object has a reference count of 1,
  237.         which will be taken care of in the dispose
  238.     */
  239.     return status;
  240. }
  241.  
  242. static TQ3Status NameAttribute_CopyAdd(
  243.     TQ3StringObject    *src,
  244.     TQ3StringObject    *dst)
  245. {
  246.     *dst = Q3Shared_GetReference(*src);
  247.     if (*dst == NULL) 
  248.         return kQ3Failure;
  249.     
  250.     return kQ3Success;
  251. }
  252.  
  253. static TQ3Status NameAttribute_CopyReplace(
  254.     TQ3StringObject    *src,
  255.     TQ3StringObject    *dst)
  256. {
  257.     TQ3StringObject    tempString;
  258.     
  259.     /*
  260.         It is always good form to get a reference first,
  261.         in case src and dst point to the same object
  262.     */
  263.     
  264.     tempString = Q3Shared_GetReference(*src);
  265.     if (tempString == NULL) 
  266.         return kQ3Failure;
  267.  
  268.     if( *dst )
  269.         Q3Object_Dispose( *dst );
  270.     
  271.     *dst = tempString;
  272.  
  273.     return kQ3Success;
  274. }
  275.  
  276. static TQ3Status NameAttribute_Delete(
  277.     TQ3StringObject    *stringObject)
  278. {
  279.     if(*stringObject)
  280.         Q3Object_Dispose(*stringObject);
  281.     return kQ3Success;
  282. }
  283.  
  284. TQ3Status NameAttribute_Unregister(
  285.     void)
  286. {
  287.     if ( gNameAttributeClass != NULL )
  288.         return    Q3ObjectClass_Unregister(gNameAttributeClass);
  289.         
  290.     return kQ3Failure;
  291. }
  292.  
  293. /*
  294.  * NameAttribute_MetaHandler
  295.  */
  296. static TQ3FunctionPointer NameAttribute_MetaHandler(
  297.     TQ3MethodType        methodType)
  298. {
  299.     switch (methodType)
  300.     {
  301.         case kQ3MethodTypeObjectTraverse:
  302.             return (TQ3FunctionPointer) NameAttribute_Traverse;
  303.         case kQ3MethodTypeObjectReadData:
  304.             return (TQ3FunctionPointer) NameAttribute_ReadData;
  305.         case kQ3MethodTypeElementCopyAdd:
  306.         case kQ3MethodTypeElementCopyGet:
  307.         case kQ3MethodTypeElementCopyDuplicate:
  308.             return (TQ3FunctionPointer) NameAttribute_CopyAdd;
  309.         case kQ3MethodTypeElementCopyReplace:
  310.             return (TQ3FunctionPointer) NameAttribute_CopyReplace;
  311.         case kQ3MethodTypeElementDelete:
  312.             return (TQ3FunctionPointer) NameAttribute_Delete;
  313.         default:
  314.             return (TQ3FunctionPointer) NULL;
  315.     }
  316. }
  317.  
  318. /*
  319.  * NameAttribute_Register
  320.  */
  321. TQ3Status NameAttribute_Register(
  322.     void)
  323. {
  324.     gNameAttributeClass = 
  325.         Q3ElementClass_Register(
  326.             kElementTypeName,
  327.             "NameAttribute",
  328.             sizeof(TQ3StringObject),
  329.             NameAttribute_MetaHandler);
  330.  
  331.     return (gNameAttributeClass == NULL ? kQ3Failure : kQ3Success);
  332. }
  333.  
  334. /**********************************************************************************************
  335.  *
  336.  *                                        SCALE custom attribute
  337.  *
  338.  **********************************************************************************************/
  339.  
  340. /*
  341.  * Utility function to add a scale on an shape object, geometry object, or attribute set
  342.  */
  343.  
  344. TQ3Status    SetScale(TQ3Object object, double scale)
  345. {
  346.     TQ3AttributeSet    set = NULL;
  347.     TQ3Status        status = kQ3Success;
  348.     
  349.     if( Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True ) {
  350.         
  351.         if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  352.             
  353.             Q3Geometry_GetAttributeSet(object, &set);
  354.             
  355.             if( set == NULL ) {
  356.                 set = Q3AttributeSet_New();
  357.                 if( set == NULL ) {
  358.                     status = kQ3Failure;
  359.                     goto cleanExit;
  360.                 }
  361.                 Q3Geometry_SetAttributeSet(object, set);
  362.             }
  363.         } else {
  364.             Q3Shape_GetSet(object, &set);
  365.             
  366.             if( set == NULL ) {
  367.                 set = Q3Set_New();
  368.                 if( set == NULL ) {
  369.                     status = kQ3Failure;
  370.                     goto cleanExit;
  371.                 }
  372.                 Q3Shape_SetSet(object, set);
  373.             }
  374.         }
  375.             
  376.         if( Q3Set_Add(set, kElementTypeScale, &scale) == kQ3Failure ) {
  377.             status = kQ3Failure;
  378.             goto cleanExit;
  379.         }
  380.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  381.         if( Q3AttributeSet_Add(object, kElementTypeScale, &scale) == kQ3Failure ) {
  382.             status = kQ3Failure;
  383.             goto cleanExit;
  384.         }
  385.     } else 
  386.         status = kQ3Failure;
  387.         
  388. cleanExit:
  389.     if( set )
  390.         Q3Object_Dispose(set);
  391.     return status;
  392. }
  393.  
  394. /*
  395.  * ScaleAttribute_Traverse
  396.  */
  397.  
  398. static TQ3Status ScaleAttribute_Traverse(
  399.     TQ3Object                unused,
  400.     TQ3Float64                *scale,
  401.     TQ3ViewObject            view)
  402. {
  403.     (void) unused;
  404.     
  405.     if (scale == NULL)
  406.         return kQ3Success;
  407.  
  408.     return Q3View_SubmitWriteData(
  409.         view, sizeof(TQ3Float64), scale, NULL);
  410. }
  411.  
  412. /*
  413.  * ScaleAttribute_Write
  414.  */
  415.  
  416. static TQ3Status ScaleAttribute_Write(
  417.     TQ3Float64                *scale,
  418.     TQ3FileObject            file)
  419. {
  420.     return 
  421.         Q3Float64_Write(*scale, file);
  422. }
  423.  
  424. /*
  425.  * ScaleAttribute_ReadData
  426.  */
  427.  
  428. static TQ3Status ScaleAttribute_ReadData(
  429.     TQ3SetObject            attributeSet,
  430.     TQ3FileObject            file)
  431. {
  432.     double            scale;
  433.     
  434.     if( Q3Float64_Read(&scale, file) == kQ3Failure) {
  435.         return kQ3Failure;
  436.     }
  437.         
  438.     return Q3Set_Add(attributeSet, kElementTypeScale, &scale);
  439. }
  440.  
  441. /*
  442.  * ScaleAttribute_MetaHandler
  443.  */
  444. static TQ3FunctionPointer ScaleAttribute_MetaHandler(
  445.     TQ3MethodType        methodType)
  446. {
  447.     switch (methodType)
  448.     {
  449.         case kQ3MethodTypeObjectTraverse:
  450.             return (TQ3FunctionPointer) ScaleAttribute_Traverse;
  451.         case kQ3MethodTypeObjectWrite:
  452.             return (TQ3FunctionPointer) ScaleAttribute_Write;
  453.         case kQ3MethodTypeObjectReadData:
  454.             return (TQ3FunctionPointer) ScaleAttribute_ReadData;
  455.         default:
  456.             return (TQ3FunctionPointer) NULL;
  457.     }
  458. }
  459.  
  460. /*
  461.  * ScaleAttribute_Register
  462.  */
  463. TQ3Status ScaleAttribute_Register(
  464.     void)
  465. {
  466.     gScaleAttributeClass = 
  467.         Q3ElementClass_Register(
  468.             kElementTypeScale,
  469.             "ScaleAttribute",
  470.             sizeof(TQ3Float64),
  471.             ScaleAttribute_MetaHandler);
  472.  
  473.     return (gScaleAttributeClass == NULL ? kQ3Failure : kQ3Success);
  474. }
  475.  
  476. /*
  477.  * ScaleAttribute_Unregister
  478.  */
  479. TQ3Status ScaleAttribute_Unregister(
  480.     void)
  481. {
  482.     if ( gScaleAttributeClass != NULL )
  483.         return    Q3ObjectClass_Unregister(gScaleAttributeClass);
  484.         
  485.     return kQ3Failure;
  486. }
  487.  
  488. /**********************************************************************************************
  489.  *
  490.  *                                common routines for dealing with vectors
  491.  *
  492.  **********************************************************************************************/
  493.  
  494. static TQ3Status vector_Traverse(
  495.     TQ3Object                unused,
  496.     TQ3Vector3D                *upVector,
  497.     TQ3ViewObject            view)
  498. {
  499.     (void) unused;
  500.     
  501.     if (upVector == NULL)
  502.         return kQ3Success;
  503.  
  504.     return Q3View_SubmitWriteData(
  505.         view, sizeof(TQ3Vector3D), upVector, NULL);
  506. }
  507.  
  508. static TQ3Status vector_Write(
  509.     TQ3Vector3D                *upVector,
  510.     TQ3FileObject            file)
  511. {
  512.     return 
  513.         Q3Vector3D_Write(upVector, file);
  514. }
  515.  
  516. static TQ3Status vector_CopyAdd(
  517.     TQ3Vector3D    *src,
  518.     TQ3Vector3D    *dst)
  519. {
  520.     *dst = *src;
  521.     return kQ3Success;
  522. }
  523.  
  524. static TQ3Status vector_CopyReplace(
  525.     TQ3Vector3D    *src,
  526.     TQ3Vector3D    *dst)
  527. {
  528.     *dst = *src;
  529.     return kQ3Success;
  530. }
  531.  
  532. /**********************************************************************************************
  533.  *
  534.  *                                        UP VECTOR custom attribute
  535.  *
  536.  **********************************************************************************************/
  537.  
  538. /*
  539.  * Utility function to specify the up vector on a group, geometry object, or attribute set
  540.  */
  541.  
  542. TQ3Status    SetUpVector(TQ3Object object, TQ3Vector3D *upVector)
  543. {
  544.     TQ3AttributeSet    set = NULL;
  545.     TQ3Status        status = kQ3Success;
  546.     
  547.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  548.         Q3Geometry_GetAttributeSet(object, &set);
  549.         
  550.         if( set == NULL ) {
  551.             set = Q3AttributeSet_New();
  552.             if( set == NULL ) {
  553.                 status = kQ3Failure;
  554.                 goto cleanExit;
  555.             }
  556.             Q3Geometry_SetAttributeSet(object, set);
  557.         }
  558.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  559.         Q3Shape_GetSet(object, &set);
  560.         
  561.         if( set == NULL ) {
  562.             set = Q3Set_New();
  563.             if( set == NULL ) {
  564.                 status = kQ3Failure;
  565.                 goto cleanExit;
  566.             }
  567.             Q3Shape_SetSet(object, set);
  568.         }
  569.     }
  570.             
  571.     if( set ) {
  572.         if( Q3Set_Add(set, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  573.             status = kQ3Failure;
  574.             goto cleanExit;
  575.         }
  576.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  577.         if( Q3AttributeSet_Add(object, kElementTypeUpVector, &upVector) == kQ3Failure ) {
  578.             status = kQ3Failure;
  579.             goto cleanExit;
  580.         }
  581.     } else 
  582.         status = kQ3Failure;
  583.         
  584. cleanExit:
  585.     if( set )
  586.         Q3Object_Dispose(set);
  587.     return status;
  588. }
  589.  
  590. /*
  591.  * UpVectorAttribute_ReadData
  592.  */
  593. static TQ3Status UpVectorAttribute_ReadData(
  594.     TQ3SetObject            attributeSet,
  595.     TQ3FileObject            file)
  596. {
  597.     TQ3Vector3D        upVector;
  598.     
  599.     if( Q3Vector3D_Read(&upVector, file) == kQ3Failure) {
  600.         return kQ3Failure;
  601.     }
  602.         
  603.     return Q3Set_Add(attributeSet, kElementTypeUpVector, &upVector);
  604. }
  605.  
  606. /*
  607.  * UpVectorAttribute_MetaHandler
  608.  */
  609. static TQ3FunctionPointer UpVectorAttribute_MetaHandler(
  610.     TQ3MethodType        methodType)
  611. {
  612.     switch (methodType)
  613.     {
  614.         case kQ3MethodTypeObjectTraverse:
  615.             return (TQ3FunctionPointer) vector_Traverse;
  616.         case kQ3MethodTypeObjectWrite:
  617.             return (TQ3FunctionPointer) vector_Write;
  618.         case kQ3MethodTypeObjectReadData:
  619.             return (TQ3FunctionPointer) UpVectorAttribute_ReadData;
  620.         case kQ3MethodTypeElementCopyAdd:
  621.         case kQ3MethodTypeElementCopyGet:
  622.         case kQ3MethodTypeElementCopyDuplicate:
  623.             return (TQ3FunctionPointer) vector_CopyAdd;
  624.         case kQ3MethodTypeElementCopyReplace:
  625.             return (TQ3FunctionPointer) vector_CopyReplace;
  626.         default:
  627.             return (TQ3FunctionPointer) NULL;
  628.     }
  629. }
  630.  
  631. /*
  632.  * UpVectorAttribute_Register
  633.  */
  634. TQ3Status UpVectorAttribute_Register(
  635.     void)
  636. {
  637.     gUpVectorAttributeClass = 
  638.         Q3ElementClass_Register(
  639.             kElementTypeUpVector,
  640.             "UpVector",
  641.             sizeof(TQ3Vector3D),
  642.             UpVectorAttribute_MetaHandler);
  643.  
  644.     return (gUpVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  645. }
  646.  
  647. /*
  648.  * UpVectorAttribute_Unregister
  649.  */
  650. TQ3Status UpVectorAttribute_Unregister(
  651.     void)
  652. {
  653.     if ( gUpVectorAttributeClass != NULL )
  654.         return    Q3ObjectClass_Unregister(gUpVectorAttributeClass);
  655.         
  656.     return kQ3Failure;
  657. }
  658.  
  659. /**********************************************************************************************
  660.  *
  661.  *                                FORWARD DIRECTION custom attribute
  662.  *
  663.  **********************************************************************************************/
  664. /*
  665.  * Utility function to add a name on a group, geometry object, or attribute set
  666.  */
  667.  
  668. TQ3Status    SetForwardDirection(TQ3Object object, TQ3Vector3D *forwardDirection)
  669. {
  670.     TQ3AttributeSet    set = NULL;
  671.     TQ3Status        status = kQ3Success;
  672.     
  673.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  674.         Q3Geometry_GetAttributeSet(object, &set);
  675.         
  676.         if( set == NULL ) {
  677.             set = Q3AttributeSet_New();
  678.             if( set == NULL ) {
  679.                 status = kQ3Failure;
  680.                 goto cleanExit;
  681.             }
  682.             Q3Geometry_SetAttributeSet(object, set);
  683.         }
  684.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ){
  685.         Q3Shape_GetSet(object, &set);
  686.         
  687.         if( set == NULL ) {
  688.             set = Q3Set_New();
  689.             if( set == NULL ) {
  690.                 status = kQ3Failure;
  691.                 goto cleanExit;
  692.             }
  693.             Q3Shape_SetSet(object, set);
  694.         }
  695.     }
  696.             
  697.     if( set ) {
  698.         if( Q3Set_Add(set, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  699.             status = kQ3Failure;
  700.             goto cleanExit;
  701.         }
  702.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  703.         if( Q3AttributeSet_Add(object, kElementTypeForwardDirection, &forwardDirection) == kQ3Failure ) {
  704.             status = kQ3Failure;
  705.             goto cleanExit;
  706.         }
  707.     } else 
  708.         status = kQ3Failure;
  709.         
  710. cleanExit:
  711.     if( set )
  712.         Q3Object_Dispose(set);
  713.     return status;
  714. }            
  715.  
  716. /*
  717.  * ForwardDirectionAttribute_ReadData
  718.  */
  719. static TQ3Status ForwardDirectionAttribute_ReadData(
  720.     TQ3SetObject            attributeSet,
  721.     TQ3FileObject            file)
  722. {
  723.     TQ3Vector3D        forwardDirection;
  724.     
  725.     if( Q3Vector3D_Read(&forwardDirection, file) == kQ3Failure) {
  726.         return kQ3Failure;
  727.     }
  728.         
  729.     return Q3Set_Add(attributeSet, kElementTypeForwardDirection, &forwardDirection);
  730. }
  731.  
  732. /*
  733.  * ForwardDirectionAttribute_MetaHandler
  734.  */
  735. static TQ3FunctionPointer ForwardDirectionAttribute_MetaHandler(
  736.     TQ3MethodType        methodType)
  737. {
  738.     switch (methodType)
  739.     {
  740.         case kQ3MethodTypeObjectTraverse:
  741.             return (TQ3FunctionPointer) vector_Traverse;
  742.         case kQ3MethodTypeObjectWrite:
  743.             return (TQ3FunctionPointer) vector_Write;
  744.         case kQ3MethodTypeObjectReadData:
  745.             return (TQ3FunctionPointer) ForwardDirectionAttribute_ReadData;
  746.         default:
  747.             return (TQ3FunctionPointer) NULL;
  748.     }
  749. }
  750.  
  751. /*
  752.  * ForwardDirectionAttribute_Register
  753.  */
  754. TQ3Status ForwardDirectionAttribute_Register(
  755.     void)
  756. {
  757.     gUpVectorAttributeClass = 
  758.         Q3ElementClass_Register(
  759.             kElementTypeForwardDirection,
  760.             "ForwardDirection",
  761.             sizeof(TQ3Vector3D),
  762.             ForwardDirectionAttribute_MetaHandler);
  763.  
  764.     return (gForwardVectorAttributeClass == NULL ? kQ3Failure : kQ3Success);
  765. }
  766.  
  767. /*
  768.  * ForwardDirectionAttribute_Unregister
  769.  */
  770. TQ3Status ForwardDirectionAttribute_Unregister(
  771.     void)
  772. {
  773.     if ( gForwardVectorAttributeClass != NULL )
  774.         return    Q3ObjectClass_Unregister(gForwardVectorAttributeClass);
  775.         
  776.     return kQ3Failure;
  777. }
  778.  
  779. /***********************************************************************************************
  780. *
  781. *    W3Anchor - This allows you attach an URL (universal resource locator) to an object or
  782. *    group.  If this attribute is attached to a group, it should be interpreted as applying
  783. *    to all the objects inside the group.
  784. *
  785. *
  786. ***********************************************************************************************/
  787.  
  788. /*
  789.  * Utility function to attach an URL reference to a group object, geometry object, or attribute set
  790.  */
  791.  
  792. TQ3Status    SetW3Anchor(TQ3Object object, char *url, char *description, W3AnchorOptions options)
  793. {
  794.     TQ3StringObject        string = NULL;
  795.     TQ3AttributeSet        set = NULL;
  796.     TQ3Status            status = kQ3Success;
  797.     W3AnchorData        W3Anchor;
  798.         
  799.     string = Q3CString_New(description);
  800.     
  801.     if( string == NULL) {
  802.         status = kQ3Failure;
  803.         goto cleanExit;
  804.     }
  805.     
  806.     W3Anchor.description = string;
  807.     W3Anchor.url = url;
  808.     W3Anchor.options = options;
  809.     
  810.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  811.         
  812.         Q3Geometry_GetAttributeSet(object, &set);
  813.         
  814.         if( set == NULL ) {
  815.             set = Q3AttributeSet_New();
  816.             if( set == NULL ) {
  817.                 status = kQ3Failure;
  818.                 goto cleanExit;
  819.             }
  820.             Q3Geometry_SetAttributeSet(object, set);
  821.         }
  822.     } else if( Q3Object_IsType(object, kQ3ShapeTypeGroup) == kQ3True ) {
  823.         Q3Shape_GetSet(object, &set);
  824.         
  825.         if( set == NULL ) {
  826.             set = Q3Set_New();
  827.             if( set == NULL ) {
  828.                 status = kQ3Failure;
  829.                 goto cleanExit;
  830.             }
  831.             Q3Shape_SetSet(object, set);
  832.         }
  833.     }
  834.     
  835.     if( set ) {        
  836.         if( Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  837.             status = kQ3Failure;
  838.             goto cleanExit;
  839.         }
  840.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  841.         if( Q3AttributeSet_Add(object, kElementTypeW3Anchor, &W3Anchor) == kQ3Failure ) {
  842.             status = kQ3Failure;
  843.             goto cleanExit;
  844.         }
  845.     } else 
  846.         status = kQ3Failure;
  847.         
  848. cleanExit:
  849.     if( set )
  850.         Q3Object_Dispose(set);
  851.     if( string )
  852.         Q3Object_Dispose(string);
  853.     return status;
  854. }
  855.  
  856. TQ3Boolean W3Anchor_GetFromObject(
  857.     TQ3Object object,
  858.     W3AnchorData *data)
  859. {
  860.     TQ3SetObject    set, tempSet;
  861.     TQ3Boolean        result = kQ3False;
  862.     
  863.     W3Anchor_Empty (data);
  864.     data->url = NULL;
  865.     data->description = NULL;
  866.     
  867.     /* must be a shape or a group */
  868.     if (Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True) 
  869.         Q3Geometry_GetAttributeSet(object, &set);
  870.     else if (Q3Object_IsType(object, kQ3SharedTypeShape) == kQ3True)
  871.         Q3Shape_GetSet (object, &set);
  872.     else
  873.         return kQ3False;
  874.  
  875.     if (set == NULL)
  876.         return kQ3False;    
  877.     
  878.     while (set != NULL)
  879.     {
  880.         if (Q3Set_Contains (set, kElementTypeW3Anchor) == kQ3True)
  881.         {
  882.             if (Q3Set_Get(set, kElementTypeW3Anchor, data) == kQ3Success)
  883.                 result = kQ3True;
  884.                 break;
  885.         }
  886.         else if (Q3Set_Contains (set, kQ3SharedTypeSet) == kQ3True)
  887.         {
  888.             tempSet = set;
  889.             if (Q3Set_Get (set, kQ3SharedTypeSet, &set) == kQ3Failure)
  890.                 break;
  891.             else
  892.                 Q3Object_Dispose (tempSet);
  893.         }
  894.         /* This is to get around a bug in releases prior to 1.0.4 PFF */
  895.         else if (Q3Set_Contains (set, kQ3ElementTypeUnknown) == kQ3True)
  896.         {
  897.             TQ3Object    unknownObject;
  898.             
  899.             if (Q3Set_Get (set, kQ3ElementTypeUnknown, &unknownObject) != kQ3Failure)
  900.             {
  901.                  TQ3ObjectType unknownType = Q3Object_GetLeafType (unknownObject);
  902.                 
  903.                 if (unknownType == kQ3SharedTypeSet)
  904.                 {
  905.                     Q3Object_Dispose (set);
  906.                     set = unknownObject;
  907.                 } 
  908.                 else if (unknownType == kQ3GroupTypeDisplay) 
  909.                 {
  910.                     TQ3GroupPosition        position;
  911.                     Q3Group_GetFirstPositionOfType (unknownObject, kQ3SharedTypeSet, &position);
  912.                     
  913.                     if (position)
  914.                     {
  915.                         tempSet = set;
  916.                         if (Q3Group_GetPositionObject(unknownObject, position, &set) == kQ3Success)
  917.                             Q3Object_Dispose (tempSet);
  918.                     }
  919.                     Q3Object_Dispose (unknownObject);
  920.                 }
  921.                 else
  922.                     Q3Object_Dispose (unknownObject);
  923.             }
  924.         }
  925.         else
  926.             break;
  927.     }
  928.  
  929.     /* throw away the reference to the set */
  930.     Q3Object_Dispose(set);
  931.     
  932.     return result;
  933. }    
  934.  
  935. TQ3Boolean W3Anchor_GetFromHitData(
  936.     const TQ3HitData *hitData, 
  937.     W3AnchorData *data)
  938. {
  939.     if (data == NULL)
  940.         return kQ3False;
  941.         
  942.     return W3Anchor_GetFromObject (hitData->object, data);
  943. }
  944.  
  945. #ifdef __cplusplus
  946. extern "C" {
  947. #endif  /* __cplusplus */
  948.  
  949. TQ3Status W3Anchor_Traverse(
  950.     TQ3Object                unused,
  951.     W3AnchorData            *URLdata,
  952.     TQ3ViewObject            view);
  953.  
  954. #ifdef __cplusplus
  955. }
  956. #endif    /* __cplusplus */
  957.  
  958. /*
  959.  * W3Anchor_Traverse
  960.  */
  961. TQ3Status W3Anchor_Traverse(
  962.     TQ3Object                unused,
  963.     W3AnchorData            *URLdata,
  964.     TQ3ViewObject            view)
  965. {
  966.     TQ3Size        size;
  967.  
  968.     (void) unused;
  969.     
  970.     if (URLdata->url == NULL)
  971.         return kQ3Success;
  972.     
  973.     size = Q3Size_Pad(strlen(URLdata->url) + 1);
  974.     size += sizeof(TQ3Uns32);
  975.     
  976.     if( Q3View_SubmitWriteData(view, size, URLdata, NULL) == kQ3Failure )
  977.         return kQ3Failure;
  978.     
  979.     if(URLdata->description) {
  980.         if( Q3Object_Submit(URLdata->description, view) == kQ3Failure )
  981.             return kQ3Failure;
  982.     }
  983.     
  984.     return kQ3Success;
  985. }
  986.  
  987. /*
  988.  * W3Anchor_Write
  989.  */
  990. static TQ3Status W3Anchor_Write(
  991.     W3AnchorData            *URLdata,
  992.     TQ3FileObject            file)
  993. {
  994.     return 
  995.         Q3String_Write(URLdata->url, file) == kQ3Success &&
  996.         Q3Uns32_Write((unsigned long) URLdata->options, file) == kQ3Success ? kQ3Success : kQ3Failure;
  997. }
  998.  
  999. /*
  1000.  * W3Anchor_ReadData
  1001.  */
  1002. static TQ3Status W3Anchor_ReadData(
  1003.     TQ3SetObject            set,
  1004.     TQ3FileObject            file)
  1005. {
  1006.     char                buf[kQ3StringMaximumLength];
  1007.     W3AnchorData        URLData = {NULL, NULL, kW3AnchorOptionNone};
  1008.     
  1009.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1010.         return kQ3Failure;
  1011.  
  1012.     URLData.url = (char *) malloc( strlen(buf) + 1);
  1013.     strcpy( URLData.url, buf);
  1014.     
  1015.     if (Q3Uns32_Read( (unsigned long *) &URLData.options, file) == kQ3Failure)
  1016.         return kQ3Failure;
  1017.     
  1018.     if( Q3File_IsEndOfContainer(file, NULL) == kQ3False ) {
  1019.         URLData.description = Q3File_ReadObject(file);
  1020.     }
  1021.     
  1022.     return Q3Set_Add(set, kElementTypeW3Anchor, &URLData);
  1023. }
  1024.  
  1025. /*
  1026.  * W3Anchor_CopyAdd
  1027.  */
  1028. static TQ3Status W3Anchor_CopyAdd(
  1029.     W3AnchorData    *src,
  1030.     W3AnchorData    *dst)
  1031. {
  1032.     long    i;
  1033.     
  1034.     if (src->url == NULL)
  1035.         return kQ3Failure;
  1036.  
  1037.     i = strlen(src->url);
  1038.     
  1039.     if (i == 0)
  1040.         return kQ3Failure;
  1041.     
  1042.     dst->url = (char *) malloc(i + 1);
  1043.     
  1044.     if (dst->url == NULL)
  1045.         return kQ3Failure;
  1046.         
  1047.     strcpy(dst->url, src->url);
  1048.     
  1049.     if( src->description ) {
  1050.         TQ3StringObject    stringReference;
  1051.         
  1052.         stringReference = Q3Shared_GetReference(src->description);
  1053.         
  1054.         if( stringReference == NULL) {
  1055.             return kQ3Failure;
  1056.         }
  1057.         
  1058.         dst->description = stringReference;
  1059.     } else
  1060.         dst->description = NULL;
  1061.         
  1062.     dst->options = src->options;
  1063.     return kQ3Success;
  1064. }
  1065.  
  1066. /*
  1067.  * W3Anchor_CopyReplace
  1068.  */
  1069. static TQ3Status W3Anchor_CopyReplace(
  1070.     W3AnchorData    *src,
  1071.     W3AnchorData    *dst)
  1072. {
  1073.     long    i;
  1074.     char    *c;
  1075.     
  1076.     if (src->url == NULL)
  1077.         return kQ3Failure;
  1078.  
  1079.     i = strlen(src->url);
  1080.     
  1081.     if (i == 0)
  1082.         return kQ3Failure;
  1083.         
  1084.     c = (char *) realloc(dst->url, i + 1);
  1085.     
  1086.     if (c == NULL)
  1087.         return kQ3Failure;
  1088.     
  1089.     dst->url = c;
  1090.         
  1091.     strcpy(dst->url, src->url);
  1092.     
  1093.     if( src->description ) {
  1094.         TQ3StringObject    stringReference;
  1095.         
  1096.         stringReference = Q3Shared_GetReference(src->description);
  1097.         
  1098.         if( stringReference == NULL) {
  1099.             return kQ3Failure;
  1100.         }
  1101.         
  1102.         if( dst->description ) {
  1103.             Q3Object_Dispose(dst->description);
  1104.         }
  1105.         
  1106.         dst->description = stringReference;
  1107.     } else
  1108.         dst->description = NULL;
  1109.         
  1110.     dst->options = src->options;
  1111.     return kQ3Success;
  1112. }
  1113.  
  1114. /*
  1115.  * W3Anchor_Delete
  1116.  */
  1117. static TQ3Status W3Anchor_Delete(
  1118.     W3AnchorData    *URLData)
  1119. {
  1120.     if (URLData->url != NULL) 
  1121.     {
  1122.         free(URLData->url);
  1123.         URLData->url = NULL;
  1124.     }
  1125.     if (URLData->description != NULL)
  1126.     {
  1127.         Q3Object_Dispose(URLData->description);
  1128.         URLData->description = NULL;
  1129.     }
  1130.  
  1131.     return kQ3Success;
  1132. }
  1133.  
  1134. /*
  1135.  * W3Anchor_MetaHandler
  1136.  */
  1137. static TQ3FunctionPointer W3Anchor_MetaHandler(
  1138.     TQ3MethodType        methodType)
  1139. {
  1140.     switch (methodType)
  1141.     {
  1142.         case kQ3MethodTypeObjectTraverse:
  1143.             return (TQ3FunctionPointer) W3Anchor_Traverse;
  1144.         case kQ3MethodTypeObjectWrite:
  1145.             return (TQ3FunctionPointer) W3Anchor_Write;
  1146.         case kQ3MethodTypeObjectReadData:
  1147.             return (TQ3FunctionPointer) W3Anchor_ReadData;
  1148.         case kQ3MethodTypeElementCopyAdd:
  1149.         case kQ3MethodTypeElementCopyGet:
  1150.         case kQ3MethodTypeElementCopyDuplicate:
  1151.             return (TQ3FunctionPointer) W3Anchor_CopyAdd;
  1152.         case kQ3MethodTypeElementCopyReplace:
  1153.             return (TQ3FunctionPointer) W3Anchor_CopyReplace;
  1154.         case kQ3MethodTypeElementDelete:
  1155.             return (TQ3FunctionPointer) W3Anchor_Delete;
  1156.         default:
  1157.             return (TQ3FunctionPointer) NULL;
  1158.     }
  1159. }
  1160.  
  1161. /*
  1162.  * W3Anchor_Register
  1163.  */
  1164. TQ3Status W3Anchor_Register(
  1165.     void)
  1166. {
  1167.     gW3AnchorClass = 
  1168.         Q3ElementClass_Register(
  1169.             kElementTypeW3Anchor,
  1170.             "W3Anchor",
  1171.             sizeof(W3AnchorData),
  1172.             W3Anchor_MetaHandler);
  1173.  
  1174.     return (gW3AnchorClass == NULL ? kQ3Failure : kQ3Success);
  1175. }
  1176.  
  1177. TQ3Status W3Anchor_Unregister(
  1178.     void)
  1179. {
  1180.     if(gW3AnchorClass)
  1181.         return Q3ObjectClass_Unregister(gW3AnchorClass);
  1182.     else
  1183.         return kQ3Success;
  1184. }
  1185.  
  1186. void W3Anchor_Empty (
  1187.     W3AnchorData *URLData)
  1188. {
  1189.     if (URLData != NULL)
  1190.         W3Anchor_Delete (URLData);
  1191. }
  1192.  
  1193.  
  1194. /***********************************************************************************************
  1195. *
  1196. *    W3Inline - Attach this to a proxy group or geometry
  1197. *
  1198. *
  1199. ***********************************************************************************************/
  1200.  
  1201. /*
  1202.  * Utility function to add a name on a group object, geometry object, or attribute set
  1203.  */
  1204.  
  1205. TQ3Status    SetW3Inline(TQ3Object object, char *url)
  1206. {
  1207.     TQ3AttributeSet        set = NULL;
  1208.     TQ3Status            status = kQ3Success;
  1209.     W3InlineData        W3Inline;
  1210.     
  1211.     W3Inline.url = url;
  1212.  
  1213.     if( Q3Object_IsType(object, kQ3ShapeTypeGeometry) == kQ3True ) {
  1214.         Q3Geometry_GetAttributeSet(object, &set);
  1215.         
  1216.         if( set == NULL ) {
  1217.             set = Q3AttributeSet_New();
  1218.             if( set == NULL ) {
  1219.                 status = kQ3Failure;
  1220.                 goto cleanExit;
  1221.             }
  1222.             Q3Geometry_SetAttributeSet(object, set);
  1223.         }
  1224.     } else     if( Q3Object_IsType(object, kQ3ShapeTypeGroup ) == kQ3True ) {
  1225.         Q3Shape_GetSet(object, &set);
  1226.         
  1227.         if( set == NULL ) {
  1228.             set = Q3Set_New();
  1229.             if( set == NULL ) {
  1230.                 status = kQ3Failure;
  1231.                 goto cleanExit;
  1232.             }
  1233.             Q3Shape_SetSet(object, set);
  1234.         }
  1235.     }
  1236.         
  1237.     if( set ) {    
  1238.         if( Q3Set_Add(set, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1239.             status = kQ3Failure;
  1240.             goto cleanExit;
  1241.         }
  1242.     } else if( Q3Object_IsType(object, kQ3SharedTypeSet) == kQ3True ) {
  1243.         if( Q3AttributeSet_Add(object, kElementTypeW3Inline, &W3Inline) == kQ3Failure ) {
  1244.             status = kQ3Failure;
  1245.             goto cleanExit;
  1246.         }
  1247.     } else 
  1248.         status = kQ3Failure;
  1249.         
  1250. cleanExit:
  1251.     if( set )
  1252.         Q3Object_Dispose(set);
  1253.     return status;
  1254. }
  1255.  
  1256. /*
  1257.  * Static Functions
  1258.  */
  1259. static TQ3Status W3Inline_Traverse(
  1260.     TQ3Object                unused,
  1261.     W3InlineData            *inlineData,
  1262.     TQ3ViewObject            view)
  1263. {
  1264.     TQ3Size        size;
  1265.     
  1266.     (void) unused;
  1267.  
  1268.     if (inlineData->url == NULL)
  1269.         return kQ3Success;
  1270.     
  1271.     size = Q3Size_Pad(strlen(inlineData->url) + 1);
  1272.     
  1273.     return
  1274.         Q3View_SubmitWriteData(view, size, inlineData, NULL);
  1275. }
  1276.  
  1277. static TQ3Status W3Inline_Write(
  1278.     W3InlineData            *inlineData,
  1279.     TQ3FileObject            file)
  1280. {
  1281.     return 
  1282.         Q3String_Write(inlineData->url, file) == kQ3Success &&
  1283.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1284. }
  1285.  
  1286. static TQ3Status W3Inline_ReadData(
  1287.     TQ3SetObject            set,
  1288.     TQ3FileObject            file)
  1289. {
  1290.     char                buf[kQ3StringMaximumLength];
  1291.     W3InlineData        inlineData;
  1292.     
  1293.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1294.         return kQ3Failure;
  1295.  
  1296.     inlineData.url = buf;
  1297.     
  1298.     return Q3Set_Add(set, kElementTypeW3Inline, &inlineData);
  1299. }
  1300.  
  1301. static TQ3Status W3Inline_CopyAdd(
  1302.     W3InlineData    *src,
  1303.     W3InlineData    *dst)
  1304. {
  1305.     long    i;
  1306.     
  1307.     if (src->url == NULL)
  1308.         return kQ3Failure;
  1309.  
  1310.     i = strlen(src->url);
  1311.     
  1312.     if (i == 0)
  1313.         return kQ3Failure;
  1314.         
  1315.     dst->url = (char *) malloc(i + 1);
  1316.     
  1317.     if (dst->url == NULL)
  1318.         return kQ3Failure;
  1319.         
  1320.     strcpy(dst->url, src->url);
  1321.     
  1322.     return kQ3Success;
  1323. }
  1324.  
  1325. static TQ3Status W3Inline_CopyReplace(
  1326.     W3InlineData    *src,
  1327.     W3InlineData    *dst)
  1328. {
  1329.     long    i;
  1330.     char    *c;
  1331.     
  1332.     if (src->url == NULL)
  1333.         return kQ3Failure;
  1334.  
  1335.     i = strlen(src->url);
  1336.     
  1337.     if (i == 0)
  1338.         return kQ3Failure;
  1339.         
  1340.     c = (char *) realloc(dst->url, i + 1);
  1341.     
  1342.     if (c == NULL)
  1343.         return kQ3Failure;
  1344.     
  1345.     dst->url = c;
  1346.         
  1347.     strcpy(dst->url, src->url);
  1348.     
  1349.     return kQ3Success;
  1350. }
  1351.  
  1352. static TQ3Status W3Inline_Delete(
  1353.     W3InlineData    *src)
  1354. {
  1355.     if (src->url != NULL) 
  1356.         free(src->url);
  1357.  
  1358.     return kQ3Success;
  1359. }
  1360.  
  1361. /*
  1362.  * W3Inline_MetaHandler
  1363.  */
  1364. static TQ3FunctionPointer W3Inline_MetaHandler(
  1365.     TQ3MethodType        methodType)
  1366. {
  1367.     switch (methodType)
  1368.     {
  1369.         case kQ3MethodTypeObjectTraverse:
  1370.             return (TQ3FunctionPointer) W3Inline_Traverse;
  1371.         case kQ3MethodTypeObjectWrite:
  1372.             return (TQ3FunctionPointer) W3Inline_Write;
  1373.         case kQ3MethodTypeObjectReadData:
  1374.             return (TQ3FunctionPointer) W3Inline_ReadData;
  1375.         case kQ3MethodTypeElementCopyAdd:
  1376.         case kQ3MethodTypeElementCopyGet:
  1377.         case kQ3MethodTypeElementCopyDuplicate:
  1378.             return (TQ3FunctionPointer) W3Inline_CopyAdd;
  1379.         case kQ3MethodTypeElementCopyReplace:
  1380.             return (TQ3FunctionPointer) W3Inline_CopyReplace;
  1381.         case kQ3MethodTypeElementDelete:
  1382.             return (TQ3FunctionPointer) W3Inline_Delete;
  1383.         default:
  1384.             return (TQ3FunctionPointer) NULL;
  1385.     }
  1386. }
  1387.  
  1388. /*
  1389.  * W3Inline_Register
  1390.  */
  1391. TQ3Status W3Inline_Register(
  1392.     void)
  1393. {
  1394.     gW3InlineClass = 
  1395.         Q3ElementClass_Register(
  1396.             kElementTypeW3Inline,
  1397.             "W3Inline",
  1398.             sizeof(W3InlineData),
  1399.             W3Inline_MetaHandler);
  1400.  
  1401.     return (gW3InlineClass == NULL ? kQ3Failure : kQ3Success);
  1402. }
  1403.  
  1404. TQ3Status W3Inline_Unregister(
  1405.     void)
  1406. {
  1407.     return Q3ObjectClass_Unregister(gW3InlineClass);
  1408. }
  1409.  
  1410.  
  1411. /***********************************************************************************************
  1412. *
  1413. *    This one is obsolete.  The code below will convert to the new type on reading and writing
  1414. *
  1415. *
  1416. ***********************************************************************************************/
  1417.  
  1418. /*
  1419.  * Static Functions
  1420.  */
  1421. static TQ3Status WWWAnchor_Traverse(
  1422.     TQ3Object                unused,
  1423.     WWWAnchorData            *wwwdata,
  1424.     TQ3ViewObject            view)
  1425. {
  1426.     TQ3Size        size;
  1427.  
  1428.     (void)unused;
  1429.     if (wwwdata->url == NULL)
  1430.         return kQ3Success;
  1431.     
  1432.     size = Q3Size_Pad(strlen(wwwdata->url) + 1);
  1433.     
  1434.     return
  1435.         Q3View_SubmitWriteData(view, size, wwwdata, NULL);
  1436. }
  1437.  
  1438. static TQ3Status WWWAnchor_Write(
  1439.     WWWAnchorData            *wwwdata,
  1440.     TQ3FileObject            file)
  1441. {
  1442.     return 
  1443.         Q3String_Write(wwwdata->url, file) == kQ3Success &&
  1444.         Q3Comment_Write("url", file) == kQ3Success ? kQ3Success : kQ3Failure;
  1445. }
  1446.  
  1447. static TQ3Status WWWAnchor_ReadData(
  1448.     TQ3SetObject            set,
  1449.     TQ3FileObject            file)
  1450. {
  1451.     char                buf[kQ3StringMaximumLength];
  1452.     WWWAnchorData        wwwdata;
  1453.     W3AnchorData        W3Anchor;
  1454.     
  1455.     if (Q3String_Read(buf, NULL, file) == kQ3Failure)
  1456.         return kQ3Failure;
  1457.  
  1458.     wwwdata.url = (char *) malloc(strlen(buf) + 1);
  1459.     strcpy(wwwdata.url, buf);
  1460.  
  1461.     W3Anchor.url = (char *) malloc(strlen(buf) + 1);
  1462.     strcpy(W3Anchor.url, buf);
  1463.      
  1464.      W3Anchor.description = NULL;
  1465.      W3Anchor.options = kW3AnchorOptionNone;
  1466.      
  1467.      Q3Set_Add(set, kElementTypeW3Anchor, &W3Anchor);
  1468.      
  1469.     return Q3Set_Add(set, kElementTypeWWWAnchor, &wwwdata);
  1470. }
  1471.  
  1472. static TQ3Status WWWAnchor_CopyAdd(
  1473.     WWWAnchorData    *src,
  1474.     WWWAnchorData    *dst)
  1475. {
  1476.     long    i;
  1477.     
  1478.     if (src->url == NULL)
  1479.         return kQ3Failure;
  1480.  
  1481.     i = strlen(src->url);
  1482.     
  1483.     if (i == 0)
  1484.         return kQ3Failure;
  1485.         
  1486.     dst->url = (char *) malloc(i + 1);
  1487.     
  1488.     if (dst->url == NULL)
  1489.         return kQ3Failure;
  1490.         
  1491.     strcpy(dst->url, src->url);
  1492.     
  1493.     return kQ3Success;
  1494. }
  1495.  
  1496. static TQ3Status WWWAnchor_CopyReplace(
  1497.     WWWAnchorData    *src,
  1498.     WWWAnchorData    *dst)
  1499. {
  1500.     long    i;
  1501.     char    *c;
  1502.     
  1503.     if (src->url == NULL)
  1504.         return kQ3Failure;
  1505.  
  1506.     i = strlen(src->url);
  1507.     
  1508.     if (i == 0)
  1509.         return kQ3Failure;
  1510.         
  1511.     c = (char *) realloc(dst->url, i + 1);
  1512.     
  1513.     if (c == NULL)
  1514.         return kQ3Failure;
  1515.     
  1516.     dst->url = c;
  1517.         
  1518.     strcpy(dst->url, src->url);
  1519.     
  1520.     return kQ3Success;
  1521. }
  1522.  
  1523. static TQ3Status WWWAnchor_Delete(
  1524.     WWWAnchorData    *src)
  1525. {
  1526.     if (src->url != NULL) 
  1527.         free(src->url);
  1528.  
  1529.     return kQ3Success;
  1530. }
  1531.  
  1532. /*
  1533.  * WWWAnchor_MetaHandler
  1534.  */
  1535. static TQ3FunctionPointer WWWAnchor_MetaHandler(
  1536.     TQ3MethodType        methodType)
  1537. {
  1538.     switch (methodType)
  1539.     {
  1540.         case kQ3MethodTypeObjectTraverse:
  1541.             return (TQ3FunctionPointer) WWWAnchor_Traverse;
  1542.         case kQ3MethodTypeObjectWrite:
  1543.             return (TQ3FunctionPointer) WWWAnchor_Write;
  1544.         case kQ3MethodTypeObjectReadData:
  1545.             return (TQ3FunctionPointer) WWWAnchor_ReadData;
  1546.         case kQ3MethodTypeElementCopyAdd:
  1547.         case kQ3MethodTypeElementCopyGet:
  1548.         case kQ3MethodTypeElementCopyDuplicate:
  1549.             return (TQ3FunctionPointer) WWWAnchor_CopyAdd;
  1550.         case kQ3MethodTypeElementCopyReplace:
  1551.             return (TQ3FunctionPointer) WWWAnchor_CopyReplace;
  1552.         case kQ3MethodTypeElementDelete:
  1553.             return (TQ3FunctionPointer) WWWAnchor_Delete;
  1554.         default:
  1555.             return (TQ3FunctionPointer) NULL;
  1556.     }
  1557. }
  1558.  
  1559. /*
  1560.  * WWWAnchor_Register
  1561.  */
  1562. TQ3Status WWWAnchor_Register(
  1563.     void)
  1564. {
  1565.     gWWWAnchorClass = 
  1566.         Q3ElementClass_Register(
  1567.             kElementTypeWWWAnchor,
  1568.             kElementNameWWWAnchor,
  1569.             sizeof(WWWAnchorData),
  1570.             WWWAnchor_MetaHandler);
  1571.  
  1572.     return (gWWWAnchorClass == NULL ? kQ3Failure : kQ3Success);
  1573. }
  1574.  
  1575. TQ3Status WWWAnchor_Unregister(
  1576.     void)
  1577. {
  1578.     return Q3ObjectClass_Unregister(gWWWAnchorClass);
  1579. }
  1580.